// import moment from "moment";
// console.log(moment())

console.log('asdfasdf');
(function () {
    function greeter(person: string) {
        return "Hello, " + person;
    }

    let user = "Jane User";

    document.body.innerHTML = greeter(user);
})();
console.log(window);

(function () {
    interface Person {
        firstName: string;
        lastName: string;
    }

    function greeter(person: Person) {
        return "Hello, " + person.firstName + " " + person.lastName;
    }

    let user = { firstName: "Jane", lastName: "User" };

    document.body.innerHTML = greeter(user);
})();

(function () {
    class Student {
        fullName: string;
        constructor(public firstName, public middleInitial, public lastName) {
            this.fullName = firstName + " " + middleInitial + " " + lastName;
        }
    }

    interface Person {
        firstName: string;
        lastName: string;
    }

    function greeter(person: Person) {
        return "Hello, " + person.firstName + " " + person.lastName;
    }

    let user = new Student("Jane", "M.", "User");

    //   let user = { firstName: "Jane", lastName: "User" };

    document.body.innerHTML = greeter(user);
})();

(function () {
    let list: number[] = [1, 2, 3];
    let list2: Array<number> = [1, 2, 3];

    // Declare a tuple type
    let x: [string, number];
    // Initialize it
    x = ["hello", 10]; // OK
    // Initialize it incorrectly
    //   x = [10, "hello"]; // Error

    console.log(x[0].substr(1)); // OK
    //   console.log(x[1].substr(1)); // Error, 'number' does not have 'substr'

    //   x[3] = "world"; // OK, 字符串可以赋值给(string | number)类型

    //   console.log(x[5].toString()); // OK, 'string' 和 'number' 都有 toString

    //   x[6] = true; // Error, 布尔不是(string | number)类型
})();

(function () {
    enum Color {
        Red,
        Green,
        Blue,
    }
    let c: Color = Color.Green;

    let notSure: any = 4;
    notSure = "maybe a string instead";
    notSure = false; // okay, definitely a boolean
})();

(function () {
    function identity<T>(arg: T): T {
        return arg;
    }
    debugger;
    let output = identity<string>("myString"); // type of output will be 'string'

    function loggingIdentity<T>(arg: T[]): T[] {
        console.log(arg.length); // Array has a .length, so no more error
        return arg;
    }

    let myAdd: (x: number, y: number) => number = function (
        x: number,
        y: number
    ): number {
        return x + y;
    };

    function a(x: number, y: number): number {
        return x + y;
    }

    // myAdd has the full function type
    let myAdd2 = function (x: number, y: number): number {
        return x + y;
    };

    // The parameters `x` and `y` have the type number
    let myAdd3: (baseValue: number, increment: number) => number = function (
        x,
        y
    ) {
        return x + y;
    };
})();



class BeeKeeper {
    hasMask: boolean;
}

class ZooKeeper {
    nametag: string;
}

class Animal {
    numLegs: number;
}

class Bee extends Animal {
    keeper: BeeKeeper;
}

class Lion extends Animal {
    keeper: ZooKeeper;
}

function createInstance<A extends Animal>(c: new () => A): A {
    return new c();
}

createInstance(Lion).keeper.nametag;  // typechecks!
createInstance(Bee).keeper.hasMask;   // typechecks!
// createInstance(ZooKeeper);   // typechecks!


function create<T>(c: { new(): T }): T {
    return new c();
}


function create2<Animal>(c: { new(): Animal }): Animal {
    return new c();
}
create(Lion)
create(Animal)
